package proxy.dissem;

import proxy.Configuration;
import proxy.Content;
import proxy.HormoneControls;
import proxy.Link;
import proxy.SearchServerNode;
import proxy.VideoUnit;
import proxy.repl.SearchServerHormoneRanking;
import simulation.Simulator;

public class HormoneDisseminationServerNode extends SearchServerHormoneRanking {

	public HormoneDisseminationServerNode(int id, Simulator simulator,
			Configuration config, HormoneControls hCtrl) {
		super(id, simulator, config, hCtrl);
	}

	@Override
	public void diffuseHormones() {
		// isolated node, we don't do anything!
		if (links.size() == 0)
			return;
		
		int preMessageCount = 0;
	
		Link bestLink = null;
		double bestOccupiedTime = simulator.getSimTime() * 2;
		// select best link
		for (Link li : links) {
			double occupiedTime = li.getOccupiedUntil()
					- simulator.getSimTime();
			if (occupiedTime < 0)
				occupiedTime = 0;
			occupiedTime += VideoUnit.getAvgSize() / li.getDatarate();
			if (occupiedTime < bestOccupiedTime) {
				bestOccupiedTime = occupiedTime;
				bestLink = li;
			}
		}

		for (Content c : hormoneTable.keySet()) {
			// spread to the neighbors
			// this is a heuristic for grading
			Double p0 = hormoneTable.get(c); // links
			Double pheromoneToSpread = p0 * hCtrl.getDiffusionAmount()
					* simulator.getSimStep();
			if (pheromoneToSpread > 0) {
				hormoneTable.put(c, p0 - pheromoneToSpread);

				// stop if unit is there, if specific unit is there also
				// general
				// hormone to it has to be stopped
				if (searchPresentUnits(c).size() > 0) {

					// check general hormones
					if (config.isSearchwithgeneralization()) {
						for (int i = 0; i < simulator.getContentTypes() - 1; i++) {
							Content general = getGeneralToTag(c, i);
							// if there is a general hormone on the node we
							// stop
							// it
							// partially
							if (general != null
									&& hormoneTable.containsKey(general)) {
								double tagValueFromGeneral = (p0 - pheromoneToSpread)
										* hCtrl.getPercentToGeneral()
										* simulator.getSimStep();

								double currentValue = hormoneTable.get(general);
								if (currentValue < tagValueFromGeneral) {
									tagValueFromGeneral = currentValue;
								}
								hormoneTable.put(general, currentValue
										- tagValueFromGeneral);

							}
						}
					}

					hormoneTable.put(c, 0.0);
					continue;
				}

				((SearchServerNode) bestLink.getTargetNode()).addHormones(c,
						pheromoneToSpread);
				preMessageCount++;

			}
		}
		//we assume that all hormones are sent within one message over the link
		if (preMessageCount > 0) {
			simulator.messageCount++;
		}
	}
}
